<template>
  <div class="v-data-and-time-setting">
    <div class="top-area">
      <div
        v-if="showTimeLine"
        class="row"
      >
        <div class="label">{{ $t("选择时间线") + ":" }}</div>
        <div class="content g-ai-c">
          <el-dropdown
            ref="timeLineDropdown"
            class="dropdown model-dropdown g-flex-1"
            :popper-options="popperOptions"
            trigger="click"
            placement="bottom-start"
          >
            <div class="dropdown-content">
              <img
                v-if="timeLine.icon"
                :src="timeLine.icon"
                alt=""
                class="g-m-r-4"
              />
              <span class="text g-one-line">{{ timeLine.label }}</span>
              <img
                src="statics/icons/app/iconlist2.png"
                alt=""
                class="_btn"
              />
            </div>
            <template #dropdown>
              <ModelDropdown
                :list="timeLineList"
                @changeOption="timeLineChange"
              ></ModelDropdown>
            </template>
          </el-dropdown>
          <div
            class="g-m-l-2 select-btn"
            @click="selectTimePoint"
          >
            ...
          </div>
        </div>
      </div>
      <div
        v-if="showTimeLine"
        class="row"
      >
        <div class="label">{{ $t("选择日期和时间") + ":" }}</div>
        <div class="content input-content">
          <el-dropdown
            ref="dateDropdown"
            class="dropdown model-dropdown"
            :popper-options="popperOptions"
            trigger="click"
            placement="bottom-start"
          >
            <div
              class="dropdown-content"
              @click.stop
            >
              <el-input
                v-model="dateString"
                @input="updateDate"
              />
              <img
                src="statics/icons/app/iconlist2.png"
                alt=""
                class="_btn"
                @click="showDateDropdown"
              />
            </div>
            <template #dropdown>
              <el-dropdown-menu>
                <el-dropdown-item
                  v-for="item in dateList"
                  :key="item.value"
                  @click="() => dateListChange(item.label)"
                >
                  {{ $t(item.label) }}
                </el-dropdown-item>
              </el-dropdown-menu>
            </template>
          </el-dropdown>
        </div>
      </div>
      <main>
        <div class="left">
          <div class="row">
            <div class="content">
              <el-calendar
                ref="calendar"
                :model-value="date"
                @update:model-value="calendarChange"
              >
                <template #header="{ date }">
                  <div class="button-area">
                    <el-button
                      size="small"
                      :icon="DArrowLeft"
                      @click="selectDate('prev-year')"
                    ></el-button>
                    <el-button
                      size="small"
                      :icon="ArrowLeft"
                      @click="selectDate('prev-month')"
                    ></el-button>
                  </div>
                  <span class="g-one-line">{{ date }}</span>
                  <div class="button-area">
                    <el-button
                      size="small"
                      :icon="ArrowRight"
                      @click="selectDate('next-month')"
                    ></el-button>
                    <el-button
                      size="small"
                      :icon="DArrowRight"
                      @click="selectDate('next-year')"
                    ></el-button>
                  </div>
                </template>
              </el-calendar>
              <el-button
                size="large"
                class="date-btn"
                @click="toToday"
              >
                {{ $t("今天") }}
              </el-button>
            </div>
          </div>
        </div>
        <div class="right">
          <div class="row">
            <div class="label">{{ $t("日期格式") + ":" }}</div>
            <div class="content">
              <el-select
                v-model="dateFormat"
                style="width: 100%"
                :suffix-icon="SelectSuffix"
                @change="updateDateString"
              >
                <el-option
                  v-for="item in dateFormatOptions"
                  :key="item.value"
                  :label="item.label"
                  :value="item.value"
                />
              </el-select>
            </div>
          </div>
          <div class="row">
            <div class="label">{{ $t("日期") + ":" }}</div>
            <div class="content date-content g-fd-c g-ai-c">
              <el-input
                ref="dateInput"
                :model-value="getDate"
              >
                <template #append>
                  <el-button
                    :icon="ArrowUp"
                    @mousedown="e => changeDate(e, 'add')"
                  />
                  <el-button
                    :icon="ArrowDown"
                    @mousedown="e => changeDate(e, 'subtract')"
                  />
                </template>
              </el-input>
              <el-button
                size="small"
                class="date-btn"
                @click="toToday"
              >
                {{ $t("选择今天") }}
              </el-button>
            </div>
          </div>
          <div class="row">
            <div class="label">{{ $t("时间") + ":" }}</div>
            <div class="content g-fd-c g-ai-c">
              <el-time-picker
                v-model="date"
                :clearable="false"
                style="width: 100%"
                @change="updateDateString"
              />
              <el-button
                size="small"
                class="date-btn"
                @click="toNow"
              >
                {{ $t("选择现在") }}
              </el-button>
            </div>
          </div>
        </div>
      </main>
      <p
        v-if="warningMsr"
        style="color: #f56c6c"
      >
        {{ warningMsr }}
      </p>
    </div>
  </div>
</template>

<script lang="ts" setup>
import { ref, watch, computed, onBeforeMount, nextTick } from "vue";
import ModelDropdown from "@/modules/model/modals/relationCriteria/components/ModelDropdown/index.vue";
import { archService } from "@/mdesign-lib/mdesign-app.umd.js";
import { modelService } from "@/mdesign-lib/mdesign-app.umd.js";
import dayjs from "dayjs";
import { ArrowUp, ArrowDown, ArrowLeft, ArrowRight, DArrowLeft, DArrowRight } from "@element-plus/icons-vue";
import { PropertyKey, PropertyDataType } from "@/mdesign-lib/mdesign-app.umd.js";
import SelectSuffix from "@/modules/model/comps/common/SelectSuffix.vue";
import { locale } from "@/mdesign-lib/mdesign-app.umd.js";
import { modelTreeSelectWindow } from "@/mdesign-lib/mdesign-app.umd.js";

interface SelectOption {
  label: string;
  value: string;
  icon?: string;
}

interface Props {
  projectId?: string;
  defaultDate?: string;
  warningMsr?: string;
  showTimeLine?: boolean;
}

const props = withDefaults(defineProps<Props>(), {
  showTimeLine: true,
  projectId: ""
});

const emit = defineEmits<{
  (e: "stepValueChange", value: any, path: string[]): void;
}>();

const timeLineDropdown = ref();
const dateDropdown = ref();
const calendar = ref();
const dateInput = ref();
const timeLine = ref<SelectOption>({ label: `<${locale.t("未指定")}>`, value: "" });
const timeLineList = ref<SelectOption[]>([]);
const dateFormat = ref("YYYY-MM-DD");
const date = ref(props.defaultDate ? dayjs(props.defaultDate).toDate() : new Date());
const dateString = ref("");
const dateFormatOptions: SelectOption[] = [
  {
    label: "YYYY",
    value: "YYYY"
  },
  {
    label: "YYYY-MM",
    value: "YYYY-MM"
  },
  {
    label: "YYYY-MM-DD",
    value: "YYYY-MM-DD"
  },
  {
    label: "YYYY-MM-DD HH:mm",
    value: "YYYY-MM-DD HH:mm"
  },
  {
    label: "YYYY-MM-DD HH:mm:ss",
    value: "YYYY-MM-DD HH:mm:ss"
  }
];
const dateListCache: Record<string, SelectOption[]> = {};
const dateList = ref<SelectOption[]>([]);

const popperOptions = computed(() => {
  return {
    modifiers: [
      {
        name: "applyStyles",
        effect: ({ state }) => {
          state.elements.popper.style.width = `${state.elements.reference.offsetWidth}px`;
          state.elements.popper.style.maxHeight = "220px";
          state.elements.popper.style.overflow = "auto";
        }
      }
    ]
  };
});

onBeforeMount(() => {
  if (props.defaultDate) {
    dateFormat.value = parseDateFormat(props.defaultDate);
  }
  if (props.showTimeLine) {
    getTimeLineList();
  }
  updateDateString();
});

watch(
  [date, dateFormat],
  () => {
    emit("stepValueChange", dayjs(date.value).format(dateFormat.value), ["date"]);
  },
  { immediate: true }
);

watch(dateString, val => {
  if (!val) {
    emit("stepValueChange", "", ["date"]);
  }
});

watch(
  timeLine,
  (val: SelectOption) => {
    emit("stepValueChange", val.value, ["timeLine"]);
  },
  { immediate: true }
);

const getDate = computed(() => {
  return dayjs(date.value).format("YYYY-MM-DD");
});

const showDateDropdown = () => {
  dateDropdown.value.handleOpen();
};

const updateDateString = () => {
  dateString.value = dayjs(date.value).format(dateFormat.value);
};

const calendarChange = (val: Date) => {
  date.value = val;
  updateDateString();
};

const updateDate = (val: string) => {
  if (dayjs(val).isValid()) {
    date.value = dayjs(val).toDate();
  }
  console.log("date", date.value);
};

const dateListChange = (val: string) => {
  dateFormat.value = parseDateFormat(val);
  updateDate(val);
  updateDateString();
};

const parseDateFormat = (val: string) => {
  const num1 = val.match(/-/g)?.length || 0;
  const num2 = val.match(/:/g)?.length || 0;
  let format = "YYYY-MM-DD";
  if (num1 === 0) {
    format = "YYYY";
  } else if (num1 === 1) {
    format = "YYYY-MM";
  } else if (num1 === 2) {
    if (num2 === 0) {
      format = "YYYY-MM-DD";
    } else if (num2 === 1) {
      format = "YYYY-MM-DD HH:mm";
    } else if (num2 === 2) {
      format = "YYYY-MM-DD HH:mm:ss";
    }
  }
  return format;
};

const changeDate = (e: Event, operate: "add" | "subtract") => {
  e.preventDefault();
  const input = dateInput.value.ref as HTMLInputElement;
  const value = input.value;
  const { firstIndex, secondIndex } = getDevideIndex(value);
  let selectionStart = input.selectionStart as number;
  if (input !== document.activeElement) {
    selectionStart = 0;
    input.focus();
  }
  let type: "day" | "month" | "year" = "year";
  if (selectionStart <= firstIndex) {
    type = "year";
  } else if (selectionStart >= firstIndex + 1 && selectionStart <= secondIndex) {
    type = "month";
  } else {
    type = "day";
  }
  addOrsubtractDate(operate, type);
  updateDateString();
  setInputSelectionRange(type);
};

const getDevideIndex = (value: string) => {
  const pattern = /-/g;
  const firstIndex = pattern.exec(value)?.index as number;
  const secondIndex = pattern.exec(value)?.index as number;
  return { firstIndex, secondIndex };
};

const setInputSelectionRange = (type: "day" | "month" | "year") => {
  nextTick(() => {
    const input = dateInput.value.ref as HTMLInputElement;
    const value = input.value;
    const { firstIndex, secondIndex } = getDevideIndex(value);
    if (type === "year") {
      input.setSelectionRange(0, firstIndex);
    } else if (type === "month") {
      input.setSelectionRange(firstIndex + 1, secondIndex);
    } else if (type === "day") {
      input.setSelectionRange(secondIndex + 1, value.length);
    }
  });
};

const addOrsubtractDate = (operate: "add" | "subtract", type: "day" | "month" | "year", num = 1) => {
  if (operate === "add") {
    date.value = dayjs(date.value).add(num, type).toDate();
  } else {
    date.value = dayjs(date.value).subtract(num, type).toDate();
  }
};

const toToday = () => {
  const currentTime = dayjs(date.value).format("HH:mm:ss");
  const currentDate = dayjs().format("YYYY-MM-DD");
  date.value = dayjs(currentDate + " " + currentTime).toDate();
  updateDateString();
};

const toNow = () => {
  const currentTime = dayjs().format("HH:mm:ss");
  const currentDate = dayjs(date.value).format("YYYY-MM-DD");
  date.value = dayjs(currentDate + " " + currentTime).toDate();
  updateDateString();
};

const getTimeLineList = async () => {
  const data = await archService.queryInstanceByType(props.projectId, "16371555332288");
  timeLineList.value = data.map(item => {
    return {
      label: item.name,
      value: item.instanceId,
      icon: item.icon
    };
  });
  if (data.length > 0) {
    timeLine.value = timeLineList.value[0];
    getDateList(timeLine.value.value);
  }
};

const getDateList = async (modelId: string) => {
  if (!dateListCache[modelId]) {
    const modelIds = await modelService
      .getPropertyValueById(props.projectId, modelId, PropertyKey.Element_ownedElement)
      .then(data => data as string[]);
    const models = await modelService.getModelDatas(props.projectId, modelIds);
    const labelObj: Record<string, boolean> = {};
    const dateOptions = models
      .filter(model => model.sts[0] === "UAF::Architecture Management::Taxonomy::ISO8601DateTime")
      .map(model => {
        return {
          icon: model.icon,
          label: model.showAttribute.extraAttribute?.value as string,
          value: model.id
        };
      })
      .filter(option => {
        const label = option.label || "";
        if (!label) return false;
        if (labelObj[label]) {
          return false;
        } else {
          labelObj[label] = true;
          return true;
        }
      });
    dateListCache[modelId] = dateOptions;
  }

  dateList.value = dateListCache[modelId];
};

const selectTimePoint = () => {
  const row = {
    modelId: "",
    key: "",
    dataType: PropertyDataType.INSTANCE,
    moreBtnCondition: "16371555332288"
  };
  modelTreeSelectWindow
    .popup({
      loadMethod: "getPropertyTreeList",
      showNodeLabel: true,
      showCreateMode: true,
      loadParams: JSON.stringify({
        row,
        projectId: props.projectId
      }),
      attrTip: "radio",
      title: "选择时间点"
    })
    .then(async res => {
      if (!res.success) return;
      const timePointModelId = res.selectedId as string;
      const timePointModel = await modelService.getModelData(props.projectId, timePointModelId);
      await getTimeLineList();
      timeLineChange({
        label: timePointModel.name,
        value: timePointModelId,
        icon: timePointModel.icon
      });
    });
};

const timeLineChange = (val: SelectOption) => {
  timeLine.value = val;
  getDateList(val.value);
  timeLineDropdown.value.handleClose();
};

const selectDate = (val: string) => {
  calendar.value.selectDate(val);
};
</script>

<style lang="scss">
.v-data-and-time-setting {
  height: 100%;
  padding: 10px;
  border: 1px solid #e4e4e4;
  .select-btn {
    height: 26px;
    width: 20px;
    border: 1px solid rgba(0, 0, 0, 0.15);
    padding: 2px;
    line-height: 24px;
    text-align: center;
    cursor: pointer;
    font-weight: bolder;
  }
  .el-dropdown {
    width: 100%;
    overflow: hidden;
    .el-tooltip__trigger {
      flex: 1;
      overflow: hidden;
    }
  }
  .model-dropdown {
    .dropdown-content {
      display: flex;
      align-items: center;
      height: 26px;
      border: 1px solid rgba(0, 0, 0, 0.15);
      padding-right: 6px;
      padding-left: 8px;
      span {
        display: inline-block;
        font-size: 12px;
        margin-right: 4px;
      }
      ._btn {
        cursor: pointer;
      }
      .el-input__wrapper {
        padding-left: 0 !important;
      }
    }
  }
  main {
    display: flex;
    .left {
      flex: 1;
    }
    .right {
      flex: 1;
      padding-left: 16px;
      .el-input-group__append {
        flex-direction: column;
        border-radius: 0;
        .el-button {
          border: 0;
          &:focus {
            border-color: unset;
            background-color: unset;
            color: unset;
          }
          &:hover {
            color: var(--el-button-hover-text-color);
          }
        }
      }
      .el-date-editor--time {
        height: 26px;
      }
      .el-input .el-input__wrapper {
        box-shadow: 0 0 0 1px #d9d9d9 inset !important;
        padding-left: 8px;
        padding-right: 10px;
        height: 26px;
        .el-input__inner {
          height: 24px;
        }
      }
      .el-select {
        .el-select__wrapper {
          box-shadow: 0 0 0 1px #d9d9d9 inset !important;
          border-radius: 0;
          height: 26px;
          .el-select__icon {
            transition: none;
          }
        }
      }
    }
  }
  .row {
    margin-bottom: 16px;
    .label {
      line-height: 16px;
      color: rgba(0, 0, 0, 0.85);
      margin-bottom: 8px;
    }
    .content {
      &.input-content {
        .el-input__wrapper {
          box-shadow: none;
          padding: 0 7px;
        }
      }
      .el-dropdown {
        height: 26px;
      }
      .el-calendar-table {
        .el-calendar-day {
          height: 50px;
        }
      }
      .el-calendar {
        border: 1px solid #d9d9d9;
        border-bottom: 1px solid rgba(0, 0, 0, 0.09);
      }
      .el-calendar__body {
        padding: 11px 17px;
        th {
          padding: 0;
          height: 30px;
        }
        td {
          border: 0;
          &.is-selected {
            background-color: #fff;
            .el-calendar-day {
              span {
                background-color: #747ad0;
                color: #fff;
              }
            }
          }
          &.is-today {
            color: #747ad0;
          }
          .el-calendar-day {
            padding: 3px;
            display: flex;
            align-items: center;
            justify-content: center;
            height: 30px;
            &:hover {
              background-color: #fff;
              span {
                background-color: #747ad0;
                color: #fff;
              }
            }
            > span {
              height: 24px;
              width: 24px;
              display: flex;
              align-items: center;
              justify-content: center;
              border-radius: 2px;
            }
          }
        }
      }
      .el-calendar__header {
        padding: 8px;
        display: flex;
        justify-content: space-between;
        align-items: center;
        border-bottom: 1px solid rgba(0, 0, 0, 0.09);
        > span {
          color: rgba(0, 0, 0, 0.85);
          font-size: 14px;
        }
        .button-area {
          white-space: nowrap;
        }
        .el-button {
          border: 0;
          color: rgba(0, 0, 0, 0.45);
          font-size: 14px;
          padding: 4px 8px;
          margin: 0;
          &:hover,
          &:focus {
            background-color: #fff;
          }
          &:hover {
            color: #747ad0;
          }
        }
      }
      &.date-content {
        .el-input-group__append {
          padding: 0 14px;
          .el-button {
            height: 12px;
            padding-top: 0;
            padding-bottom: 0;
            &:hover {
              color: #747ad0;
            }
          }
        }
      }
    }
    .date-btn {
      width: 100%;
      color: #747ad0;
      border: 1px solid #d9d9d9;
      border-top: 0;
      border-radius: 0;
      &:hover,
      &:focus {
        background-color: #fff;
      }
    }
  }
  .text {
    text-overflow: ellipsis;
    white-space: nowrap;
    overflow: hidden;
    line-height: 14px;
    flex: 1;
  }
}
</style>
